package nl.altenpts.net.kad;

import java.security.spec.InvalidKeySpecException;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import nl.altenpts.net.NetReactor;
import nl.altenpts.net.broker.IncomingMessage;
import nl.altenpts.net.broker.ResponseHandler;

/**
 * 
 *  
 * @author phub4r
 *
 */
public class ValueOperation extends Operation {
	
	public ValueOperation(byte[] key, KBroker broker, List<Node> nodes,
			Callback callback, NetReactor reactor) {
		super(nodes, Kademlia.keyToId(key), reactor, callback);
		
		this.broker = broker;
		this.key = key;
	}
	

	
	protected synchronized void sendRequest(Node n) {
		if(n != null) {
			broker.ValueRequest(n, key, new ValueResponseHandler(n));
		} else {
			finish();
		}
	}
	
	private class ValueResponseHandler implements ResponseHandler {
		
		public ValueResponseHandler(Node n) {
			node = n;
		}

		public void onResponse(IncomingMessage response) {
			byte responsetype = response.getPayload().get();
			switch(responsetype) {

			case KBroker.KADBROKER_NODE_RESPONSE:
				try {
					List<Node> newnodes = KBroker.parseNodeList(response.getPayload());					
					addNodes(newnodes);
				} catch (Exception e) {
					//ignore
				}

				break;
			case KBroker.KADBROKER_VALUE_RESPONSE:
				try {
					Set<Value> newvalues = KBroker.parseValueList(response.getPayload());
					Iterator<Value> iterator = newvalues.iterator();

					while(iterator.hasNext()) 
					{
						Value value = iterator.next();
						if( !valueList.contains(value) )
						{
							valueList.add(value);
							respond(value);
						} else { System.out.println("List already has value");}
					}
				} catch (InvalidKeySpecException e) {
					//ignore
				}
				break;                          
			}
			nodeResponded(node, STATE_ANSWERED);
					
		}

		public void onTimeout() {
			nodeResponded(node, STATE_TIMEDOUT);			
		}
		
		private Node node;
		
	}


	private KBroker broker;
	private byte[] key;
	// private List<Value> valueList = Collections.synchronizedList( new LinkedList< Value >() ); 
	private List<Value> valueList = new LinkedList< Value >();

}
